using System;
using System.Collections.Generic;
using System.Collections;
using CommonTypes;
using System.Text;
using System.Runtime.Serialization;
using System.ComponentModel;
using MVCFramework;

namespace BuildingStructuralElements
{
    [Serializable]
    [TypeConverter(typeof(ExpandableObjectConverter))]
    public abstract class Section : IVisitorHost, ISerializable,IModelData ,ICloneable 
    {
        private string name;

        [NonSerialized]
        public bool needsUpdate;

        public bool NeedsUpdate
        {
            get { return true ; }
            set { needsUpdate = value; }
        }
        [NonSerialized]
        public Hashtable HashTable = null;

        public string XmlDataPath = "";

        #region Properties

        [Description("Element Name"), Category("Name")]
        public virtual string Name
        {
            set { name = value; }
            get { return name; }
        }


        #endregion

        public Section()
        {
            name = "Section";
            needsUpdate = true;
        }

        public override string ToString()
        {
            return name;
        }

        public void Accept(IVisitor visitor)
        {
            visitor.Visit(this);
        }

        #region Serialization
        protected Section(SerializationInfo info, StreamingContext context)
        {
            string version = info.GetString("SectionVersion");

            // Make sure file format is not newer than the application:
            if (String.Compare(version, "1.0") > 0)
            {
                throw new Exception("Invalid Section File Version!");
            }

            if (String.Compare(version, "1.0") >= 0)
            {
                name = info.GetString("Name");

            }

        }

        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("SectionVersion", "1.0"); // The class version
            info.AddValue("Name", name);
        }
        #endregion

        #region ICloneable Members

        public object Clone()
        {
            
            System.IO.MemoryStream memoryStream = new System.IO.MemoryStream();
            System.Runtime.Serialization.Formatters.Binary.BinaryFormatter binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();

            binaryFormatter.Serialize(memoryStream, this);
            memoryStream.Seek(0, System.IO.SeekOrigin.Begin);

            Section  section = (Section )binaryFormatter.Deserialize(memoryStream);
            section.needsUpdate =true;

            return section;
        }

        #endregion
    }


    [Serializable]
    public class SectionIRolled : Section, ISerializable
    {
        private double h;  //section height
        private double b;  //section width
        private double t;  //section thickness flange
        private double s;  //section thickness web
        private double r;  //radius

        #region Properties

        /// <summary>
        /// Section Height
        /// </summary>
        [Description("Height"), Category("Geometry")]
        [UnitConverterAttribute("Lenght")]
        public double H
        {
            get { return h; }
            set
            {
                h = value;
                NeedsUpdate = true;
            }

        }

        [Description("Width"), Category("Geometry")]
        [UnitConverterAttribute("Lenght")]
        public double B
        {
            get { return b; }
            set
            {
                b = value;
                NeedsUpdate = true;
            }

        }

        [Description("Flange Thickness"), Category("Geometry")]
        public double T
        {
            get { return t; }
            set
            {
                t = value;
                NeedsUpdate = true;
            }

        }

        [Description("Web Thickness"), Category("Geometry")]
        public double S
        {
            get { return s; }
            set
            {
                s = value;
                NeedsUpdate = true;
            }

        }

        [Description("Radius"), Category("Geometry")]
        public double R
        {
            get { return r; }
            set
            {
                r = value;
                NeedsUpdate = true;
            }

        }


        #endregion

        public SectionIRolled()
        {
            h = 0.3f;
            b = 0.2f;
            t = 0.01f;
            s = 0.01f;
            r = 0.01f;

            Name = "IRolledSection";

        }

        public SectionIRolled(string name, double H, double B, double T, double S, double R)
        {
            h = H;
            b = B;
            t = T;
            s = S;
            r = R;

            Name = name;

        }

        #region Serialization
        protected SectionIRolled(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
            string version = info.GetString("IRolledSectionVersion");

            // Make sure file format is not newer than the application:
            if (String.Compare(version, "1.0") > 0)
            {
                throw new Exception("Invalid IRolledSection File Version!");
            }

            if (String.Compare(version, "1.0") >= 0)
            {
                h = info.GetDouble("H");
                b = info.GetDouble("B");
                t = info.GetDouble("T");
                s = info.GetDouble("S");
                r = info.GetDouble("T");

            }

        }

        public new void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);

            info.AddValue("IRolledSectionVersion", "1.0"); // The class version
            info.AddValue("H", h);
            info.AddValue("B", b);
            info.AddValue("T", t);
            info.AddValue("S", s);
            info.AddValue("R", r);

        }
        #endregion
    }


    [Serializable]
    public class SectionIWelded : Section, ISerializable
    {
        private double hw;  //web height
        private double tw; //web thickness
        private double buf;  //width upper flange
        private double blf;  //width lower flange
        private double tuf; //upper flange thickness
        private double tlf; //lower flange thickness

        #region Properties


        [Description("Web Height"), Category("Geometry")]
        public double Hw
        {
            get { return hw; }
            set
            {
                hw = value;
                NeedsUpdate = true;
            }

        }


        [Description("Web Thickness"), Category("Geometry")]
        public double Tw
        {
            get { return tw; }
            set
            {
                tw = value;
                NeedsUpdate = true;
            }

        }


        [Description("Upper Flange Width"), Category("Geometry")]
        public double Buf
        {
            get { return buf; }
            set
            {
                buf = value;
                NeedsUpdate = true;
            }

        }


        [Description("LowerFlange Width"), Category("Geometry")]
        public double Blf
        {
            get { return blf; }
            set
            {
                blf = value;
                NeedsUpdate = true;
            }

        }


        [Description("Upper Flange Thickness"), Category("Geometry")]
        public double Tuf
        {
            get { return tuf; }
            set
            {
                tuf = value;
                NeedsUpdate = true;
            }

        }


        [Description("Lower Flange Thickness"), Category("Geometry")]
        public double Tlf
        {
            get { return tlf; }
            set
            {
                tlf = value;
                NeedsUpdate = true;
            }

        }


        #endregion

        public SectionIWelded()
        {
            hw = 60.0f;
            tw = 3.8f;
            buf = 46.0f;
            tuf = 5.2f;
            blf = 64.0f;
            tlf = 6.3f;

            Name = "IWeldedSection";

        }

        public SectionIWelded(string name, double Hw, double Tw, double Buf, double Blf, double Tuf, double Tlf)
        {
            hw = Hw;
            tw = Tw;
            buf = Buf;
            tuf = Tuf;
            blf = Blf;
            tlf = Tlf;

            Name = name;
        }


        #region Serialization
        protected SectionIWelded(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
            string version = info.GetString("IWeldedSectionVersion");

            // Make sure file format is not newer than the application:
            if (String.Compare(version, "1.0") > 0)
            {
                throw new Exception("Invalid IWeldedSection File Version!");
            }

            if (String.Compare(version, "1.0") >= 0)
            {
                hw = info.GetDouble("Hw");
                tw = info.GetDouble("Tw");

                buf = info.GetDouble("Buf");
                blf = info.GetDouble("Blf");
                tuf = info.GetDouble("Tuf");
                tlf = info.GetDouble("Tlf");

            }

        }

        public new void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);

            info.AddValue("IWeldedSectionVersion", "1.0"); // The class version

            info.AddValue("Hw", hw);
            info.AddValue("Tw", tw);

            info.AddValue("Buf", buf);
            info.AddValue("Blf", blf);
            info.AddValue("Tuf", tuf);
            info.AddValue("Tlf", tlf);

        }
        #endregion
    }


    [Serializable]
    public class SectionL : Section, ISerializable
    {
        double h;  //height
        double b;  //width
        double t;  //thickness
        double r;  //radius

        #region Properties

        [Description("Height"), Category("Geometry")]
        public double H
        {
            get { return h; }
            set
            {
                h = value;
                NeedsUpdate = true;
            }

        }


        [Description("Width"), Category("Geometry")]
        public double B
        {
            get { return b; }
            set
            {
                b = value;
                NeedsUpdate = true;
            }

        }


        [Description("Thickness"), Category("Geometry")]
        public double T
        {
            get { return t; }
            set
            {
                t = value;
                NeedsUpdate = true;
            }

        }


        [Description("Radius"), Category("Geometry")]
        public double R
        {
            get { return r; }
            set
            {
                r = value;
                NeedsUpdate = true;
            }

        }


        #endregion

        public SectionL()
        {
            h = 1.0f;
            b = 1.0f;
            t = 0.1f;
            r = 0.10f;

            Name = "LSection";
        }

        public SectionL(string name, double H, double B, double T, double R)
        {
            h = H;
            b = B;
            t = T;
            r = R;

            Name = name;
        }


        #region Serialization
        protected SectionL(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
            string version = info.GetString("LSectionVersion");

            // Make sure file format is not newer than the application:
            if (String.Compare(version, "1.0") > 0)
            {
                throw new Exception("Invalid LSection File Version!");
            }

            if (String.Compare(version, "1.0") >= 0)
            {
                h = info.GetDouble("H");
                b = info.GetDouble("B");

                t = info.GetDouble("T");
                r = info.GetDouble("R");
            }

        }

        public new void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);

            info.AddValue("LSectionVersion", "1.0"); // The class version

            info.AddValue("H", h);
            info.AddValue("B", b);
            info.AddValue("T", t);
            info.AddValue("R", r);
        }
        #endregion
    }


    [Serializable]
    public class SectionL2 : Section, ISerializable
    {
        double h;  //height
        double b;  //width
        double t;  //thickness
        double r;  //radius
        double tp;  //plate thickness

        #region Properties

        [Description("Height"), Category("Geometry")]
        public double H
        {
            get { return h; }
            set
            {
                h = value;
                NeedsUpdate = true;
            }

        }


        [Description("Width"), Category("Geometry")]
        public double B
        {
            get { return b; }
            set
            {
                b = value;
                NeedsUpdate = true;
            }

        }


        [Description("Thickness"), Category("Geometry")]
        public double T
        {
            get { return t; }
            set
            {
                t = value;
                NeedsUpdate = true;
            }

        }


        [Description("Radius"), Category("Geometry")]
        public double R
        {
            get { return r; }
            set
            {
                r = value;
                NeedsUpdate = true;
            }

        }


        [Description("Plate Thickness"), Category("Geometry")]
        public double Tp
        {
            get { return tp; }
            set
            {
                tp = value;
                NeedsUpdate = true;
            }

        }


        #endregion

        public SectionL2()
        {
            h = 70.0f;
            b = 70.0f;
            t = 6.0f;
            r = 9.0f;
            tp = 6.0f;

            Name = "L2Section";

        }

        public SectionL2(string name, double H, double B, double T, double R, double Tp)
        {
            h = H;
            b = B;
            t = T;
            r = R;
            tp = Tp;

            Name = name;

        }


        #region Serialization
        protected SectionL2(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
            string version = info.GetString("L2SectionVersion");

            // Make sure file format is not newer than the application:
            if (String.Compare(version, "1.0") > 0)
            {
                throw new Exception("Invalid L2Section File Version!");
            }

            if (String.Compare(version, "1.0") >= 0)
            {
                h = info.GetDouble("H");
                b = info.GetDouble("B");
                t = info.GetDouble("T");
                r = info.GetDouble("R");
                tp = info.GetDouble("Tp");
            }

        }

        public new void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);

            info.AddValue("L2SectionVersion", "1.0"); // The class version

            info.AddValue("H", h);
            info.AddValue("B", b);
            info.AddValue("T", t);
            info.AddValue("R", r);
            info.AddValue("Tp", tp);
        }
        #endregion

    }


    [Serializable]
    public class SectionSHS : Section, ISerializable
    {
        double h;  //height
        double t;  //thickness
        double re; //external r
        double ri; //internal r

        #region Properties


        [Description("Height"), Category("Geometry")]
        public double H
        {
            get { return h; }
            set
            {
                NeedsUpdate = true;
                h = value;
            }

        }


        [Description("Thickness"), Category("Geometry")]
        public double T
        {
            get { return t; }
            set
            {
                t = value;
                NeedsUpdate = true;
            }

        }


        [Description("External Radius"), Category("Geometry")]
        public double Re
        {
            get { return re; }
            set
            {
                re = value;
                NeedsUpdate = true;
            }

        }


        [Description("Internal Radius"), Category("Geometry")]
        public double Ri
        {
            get { return ri; }
            set
            {
                ri = value;
                NeedsUpdate = true;
            }

        }


        #endregion

        public SectionSHS()
        {
            h = 70.0f;
            t = 6.0f;
            re = 6.0f;
            ri = 3.0f;

            Name = "SHSSection";
        }

        public SectionSHS(string name, double H, double T, double Re, double Ri)
        {
            h = H;
            t = T;
            re = Re;
            ri = Ri;

            Name = name;
        }

        #region Serialization
        protected SectionSHS(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
            string version = info.GetString("SHSSectionVersion");

            // Make sure file format is not newer than the application:
            if (String.Compare(version, "1.0") > 0)
            {
                throw new Exception("Invalid SHSSection File Version!");
            }

            if (String.Compare(version, "1.0") >= 0)
            {
                h = info.GetDouble("H");
                t = info.GetDouble("T");
                re = info.GetDouble("Re");
                ri = info.GetDouble("Ri");
            }

        }

        public new void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);

            info.AddValue("SHSSectionVersion", "1.0"); // The class version

            info.AddValue("H", h);
            info.AddValue("T", t);
            info.AddValue("Re", re);
            info.AddValue("Ri", ri);
        }
        #endregion

    }


    [Serializable]
    public class SectionRHS : Section, ISerializable
    {
        double h;  //height
        double b;  //width
        double t;  //thickness
        double re; //external r
        double ri; //internal r

        #region Properties


        [Description("Height"), Category("Geometry")]
        public double H
        {
            get { return h; }
            set
            {
                h = value;
                NeedsUpdate = true;
            }

        }


        [Description("Width"), Category("Geometry")]
        public double B
        {
            get { return b; }
            set
            {
                b = value;
                NeedsUpdate = true;
            }

        }


        [Description("Thickness"), Category("Geometry")]
        public double T
        {
            get { return t; }
            set
            {
                t = value;
                NeedsUpdate = true;
            }

        }


        [Description("External Radius"), Category("Geometry")]
        public double Re
        {
            get { return re; }
            set
            {
                re = value;
                NeedsUpdate = true;
            }

        }


        [Description("Internal Radius"), Category("Geometry")]
        public double Ri
        {
            get { return ri; }
            set
            {
                ri = value;
                NeedsUpdate = true;
            }

        }


        #endregion

        public SectionRHS()
        {
            h = 70.0f;
            b = 30.0f;
            t = 6.0f;
            re = 6.0f;
            ri = 3.0f;

            Name = "RHSSection";

        }

        public SectionRHS(string name, double H, double B, double T, double Re, double Ri)
        {
            h = H;
            b = B;
            t = T;
            re = Re;
            ri = Ri;

            Name = name;
        }


        #region Serialization
        protected SectionRHS(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
            string version = info.GetString("RHSSectionVersion");

            // Make sure file format is not newer than the application:
            if (String.Compare(version, "1.0") > 0)
            {
                throw new Exception("Invalid RHSSection File Version!");
            }

            if (String.Compare(version, "1.0") >= 0)
            {
                h = info.GetDouble("H");
                b = info.GetDouble("B");
                t = info.GetDouble("T");
                re = info.GetDouble("Re");
                ri = info.GetDouble("Ri");
            }

        }

        public new void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);

            info.AddValue("RHSSectionVersion", "1.0"); // The class version

            info.AddValue("H", h);
            info.AddValue("B", b);
            info.AddValue("T", t);
            info.AddValue("Re", re);
            info.AddValue("Ri", ri);
        }
        #endregion
    }


    [Serializable]
    public class SectionCHS : Section, ISerializable
    {
        double d;  //outer diameter
        double t;  //thickness

        #region Properties


        [Description("Outer Diameter"), Category("Geometry")]
        public double D
        {
            get { return d; }
            set
            {
                d = value;
                NeedsUpdate = true;
            }

        }


        [Description("Thickness"), Category("Geometry")]
        public double T
        {
            get { return t; }
            set
            {
                t = value;
                NeedsUpdate = true;
            }

        }


        #endregion

        public SectionCHS()
        {
            d = 0.5f;
            t = 0.03f;

            Name = "CHSSection";
        }

        public SectionCHS(string name, double D, double T)
        {
            d = D;
            t = T;

            Name = name;
        }


        #region Serialization
        protected SectionCHS(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
            string version = info.GetString("CHSSectionVersion");

            // Make sure file format is not newer than the application:
            if (String.Compare(version, "1.0") > 0)
            {
                throw new Exception("Invalid CHSSection File Version!");
            }

            if (String.Compare(version, "1.0") >= 0)
            {
                d = info.GetDouble("D");
                t = info.GetDouble("T");
            }

        }

        public new void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);

            info.AddValue("CHSSectionVersion", "1.0"); // The class version

            info.AddValue("D", d);
            info.AddValue("T", t);
        }
        #endregion
    }


    [Serializable]
    public class SectionUPN : Section, ISerializable
    {
        double h;   //height
        double b;   //width
        double tw;   //thickness web
        double tf;   //thickness flange
        double r1;  //radius of corner 
        double r2;  //radius of edge 

        #region Properties


        [Description("Height"), Category("Geometry")]
        public double H
        {
            get { return h; }
            set
            {
                NeedsUpdate = true;
                h = value;
            }

        }

        [Description("Width"), Category("Geometry")]
        public double B
        {
            get { return b; }
            set
            {
                b = value;
                NeedsUpdate = true;
            }

        }


        [Description("Thickness Flange"), Category("Geometry")]
        public double Tf
        {
            get { return tf; }
            set
            {
                tf = value;
                NeedsUpdate = true;
            }

        }

        [Description("Thickness Web"), Category("Geometry")]
        public double Tw
        {
            get { return tw; }
            set
            {
                tw = value;
                NeedsUpdate = true;
            }

        }


        [Description("Corner Radius"), Category("Geometry")]
        public double R1
        {
            get { return r1; }
            set
            {
                r1 = value;
                NeedsUpdate = true;
            }

        }

        [Description("Edge Radius"), Category("Geometry")]
        public double R2
        {
            get { return r2; }
            set
            {
                r2 = value;
                NeedsUpdate = true;
            }

        }

        #endregion

        public SectionUPN()
        {
            h = 80.0f;
            b = 45.0f;
            tw = 6.0f;
            tf = 8.0f;
            r1 = 8.0f;
            r2 = 4.0f;

            Name = "UPNSection";

        }

        public SectionUPN(string name, double H, double B, double Tw, double Tf, double R1, double R2)
        {
            h = H;
            b = B;
            tw = Tw;
            tf = Tf;
            r1 = R1;
            r2 = R2;

            Name = name;
        }


        #region Serialization
        protected SectionUPN(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
            string version = info.GetString("UPNSectionVersion");

            // Make sure file format is not newer than the application:
            if (String.Compare(version, "1.0") > 0)
            {
                throw new Exception("Invalid UPNSection File Version!");
            }

            if (String.Compare(version, "1.0") >= 0)
            {
                h = info.GetDouble("H");
                b = info.GetDouble("B");

                tw = info.GetDouble("Tw");
                tf = info.GetDouble("Tf");

                r1 = info.GetDouble("r1");
                r2 = info.GetDouble("r2");
            }

        }

        public new void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);

            info.AddValue("UPNSectionVersion", "1.0"); // The class version

            info.AddValue("H", h);
            info.AddValue("B", b);

            info.AddValue("Tw", tw);
            info.AddValue("Tf", tf);

            info.AddValue("r1", r1);
            info.AddValue("r2", r2);
        }
        #endregion
    }


    [Serializable]
    public class SectionIPN : Section, ISerializable
    {
        double h;   //height
        double h1;  //space between fillets
        double b;   //width
        double t;   //thickness
        double r1;  //radius of corner 
        double r2;  //radius of edge 

        #region Properties


        [Description("Height"), Category("Geometry")]
        public double H
        {
            get { return h; }
            set
            {
                h = value;
                NeedsUpdate = true;
            }

        }


        [Description("Space Between Fillets"), Category("Geometry")]
        public double H1
        {
            get { return h1; }
            set
            {
                h1 = value;
                NeedsUpdate = true;
            }

        }


        [Description("Width"), Category("Geometry")]
        public double B
        {
            get { return b; }
            set
            {
                b = value;
                NeedsUpdate = true;
            }

        }


        [Description("Thickness"), Category("Geometry")]
        public double T
        {
            get { return t; }
            set
            {
                t = value;
                NeedsUpdate = true;
            }

        }


        [Description("Corner Radius"), Category("Geometry")]
        public double R1
        {
            get { return r1; }
            set
            {
                r1 = value;
                NeedsUpdate = true;
            }

        }

        [Description("Edge Radius"), Category("Geometry")]
        public double R2
        {
            get { return r2; }
            set
            {
                r2 = value;
                NeedsUpdate = true;
            }

        }


        #endregion

        public SectionIPN()
        {
            h = 100.0f;
            h1 = 75.0f;
            b = 50.0f;
            t = 6.6f;
            r1 = 4.5f;
            r2 = 2.7f;

            Name = "IPNSection";
        }

        public SectionIPN(string name, double H, double H1, double B, double T, double R1, double R2)
        {
            h = H;
            h1 = H1;
            b = B;
            t = T;
            r1 = R1;
            r2 = R2;

            Name = name;
        }


        #region Serialization
        protected SectionIPN(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
            string version = info.GetString("IPNSectionVersion");

            // Make sure file format is not newer than the application:
            if (String.Compare(version, "1.0") > 0)
            {
                throw new Exception("Invalid IPNSection File Version!");
            }

            if (String.Compare(version, "1.0") >= 0)
            {
                h = info.GetDouble("H");
                h1 = info.GetDouble("H1");
                b = info.GetDouble("B");
                t = info.GetDouble("T");

                r1 = info.GetDouble("r1");
                r2 = info.GetDouble("r2");
            }

        }

        public new void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);

            info.AddValue("IPNSectionVersion", "1.0"); // The class version

            info.AddValue("H", h);
            info.AddValue("H1", h1);
            info.AddValue("B", b);
            info.AddValue("T", t);

            info.AddValue("r1", r1);
            info.AddValue("r2", r2);
        }
        #endregion
    }
}
